home *** CD-ROM | disk | FTP | other *** search
/ Maclife 157 / MACLIFE157-2001-09.ISO.7z / MACLIFE157-2001-09.ISO / Linux / MacOS Tools / Other / BootX 1.1.3 (for Old Mac OS) / Sources / src / bootstrap.c next >
Text File  |  2001-07-23  |  5KB  |  221 lines

  1. /* This is BootX boostrap. This code is called by BootX in supervisor mode
  2.  * with whatever mappings have been set by MacOS.
  3.  *
  4.  * The unmangler will first move itself up in memory in case it's current location
  5.  * overlaps the destination of the kernel. The boostrap copies itself
  6.  * and jump to the new bootstrap code.
  7.  *
  8.  * Note that all "decisions" regarding this copy are taken by BootX, the stack
  9.  * pointer (r1) is already set to the destination stack for the kernel
  10.  * (the boostrap has no stack).
  11.  *
  12.  * Then, it will copy kernel pages to their destination from a map passed in
  13.  * by BootX. This map is appended to the unmangler and a pointer to it is
  14.  * passed in r9 (pointer to the destination location of the unmangler).
  15.  * This map is actually a kind of "script" with a serie of copy operations
  16.  * to perform (a list of src/dest/size entries).
  17.  *
  18.  * Registers on entry:
  19.  *
  20.  * r2  = 1 on entry by BootX
  21.  * r3  = 0x426f6f58    ('BooX')
  22.  * r4  = pointer to boot_infos (in kernel destination)
  23.  * r5  = fb address (for BAT mapping)
  24.  * r6  = physical address of me
  25.  * r7  = physical address where I must be copied.
  26.  * r8  = size to copy (size of unmangler)
  27.  * r9  = unmangle map (pointer to list of copy operations)
  28.  * r10 = kernel entry in destination
  29.  * r11 = 1 indicates need to setup a BAT mapping
  30.  *
  31.  * The unmangle map is a list of tuples of 3 longs each: a source address,
  32.  * a destination address, and a size. A size of zero indicates the end of
  33.  * the list.
  34.  *
  35.  * Portions of this code from Gabriel Paubert's PReP bootloader, other
  36.  * portions from the Linux kernel itself (arch/ppc/kernel/head.S)
  37.  *
  38.  */
  39.  
  40. #include "processor.h"
  41.  
  42. #ifndef BROKEN_THIRD_PARTY_CARDS
  43. #define BROKEN_THIRD_PARTY_CARDS    1
  44. #endif
  45.  
  46. #if BROKEN_THIRD_PARTY_CARDS
  47. #define __sync(x)        ¥
  48.     li r0,0;            ¥
  49.     cmpwi r0,0;            ¥
  50.     bne+ toto##x;        ¥
  51.     sync;                ¥
  52. toto##x:
  53. #else
  54. #define __sync(x)        sync
  55. #endif
  56.     
  57.  
  58. asm void start(void)
  59. {
  60. first_bootstrap:    
  61.     /* Disable interrupts (clear MSR_EE). rlwinm is more "smart"
  62.        but less readable (our constants are bit masks). */
  63.     mfmsr    r0
  64.     ori        r0,r0,MSR_EE
  65.     xori    r0,r0,MSR_EE
  66.     mtmsr    r0
  67.     __sync(0)
  68.  
  69.     /* Check if MMU was already turned off */
  70.     cmplwi    r2,0
  71.     beq        already_off
  72.  
  73.     /* turn the MMU off */
  74.     mfmsr    r0
  75.     ori        r0,r0,MSR_IR|MSR_DR    /* |MSR_IP */
  76.     li        r2,0
  77.     xori    r0,r0,MSR_IR|MSR_DR    /* |MSR_IP */
  78.     mtsrr0    r6
  79.     mtsrr1    r0
  80.     __sync(1)        /* I heard that some 601 will like this one */
  81.     rfi
  82.  
  83. already_off:
  84.     /* save some parameters */    
  85.     mr        r31,r3
  86.     mr        r30,r4
  87.     mr        r29,r5
  88.  
  89.     /* flush TLBs, ivalidate BATs */
  90.     bl        flush_tlb
  91.     bl        inval_BATs
  92.     
  93.     /* Need to copy myself ? */
  94.     cmpw    r6,r7
  95.     beq        skip_copy
  96.     
  97.     /* Copy ourselves */
  98.     mr        r3,r7
  99.     mr        r4,r6
  100.     mr        r5,r8
  101.     li        r6,0
  102.     bl        copy_and_flush
  103.     
  104.     mr        r6, r7        /* update address of me */
  105.     mr        r3,r31        /* restore parameters */
  106.     mr        r4,r30
  107.     mr        r5,r29
  108.     li        r2,0        /* not necessary since no code here changes it, but... */
  109.     mtlr    r7            /* Jump to copy of me (*) */
  110.     blr
  111.     
  112. /* (*) note that we jump at the beginning of the copy. We could jump
  113.        to skip_copy directly if CW knew how to calculate the offset
  114.        directly in the inline assembler. This will be done in the next
  115.        version of the compiler, in the meantime, we just re-enter at
  116.        the beginning
  117.  */
  118.  
  119. skip_copy:
  120.     
  121.     /* Call unmangle code */
  122.     bl        unmangle_kernel
  123.     
  124.     /* Jump to kernel */
  125.     mr        r3,r31            /* restore parameters */
  126.     mr        r4,r30
  127.     li        r5,0            /* clear r5 */
  128.     mtlr    r10
  129.     blr
  130.  
  131. /* Unmangle kernel code. This routine will read the array prepared by
  132.  * BootX and follow instructions in it for copying kernel pages until
  133.  * the kernel is fully reconstitued
  134.  */
  135. unmangle_kernel:
  136.      mflr    r13
  137. unmangle_loop:    
  138.      lwz        r4,0(r9)
  139.      lwz        r3,4(r9)
  140.      lwz        r5,8(r9)
  141.      li        r6,0
  142.      addi    r9,r9,12
  143.      cmpwi    r5,0
  144.      beq        unmangle_finish
  145.      bl        copy_and_flush
  146.      b        unmangle_loop
  147. unmangle_finish:
  148.     mtlr    r13
  149.      blr
  150.  
  151. /*
  152.  * Copy routine used to copy a piece of code and flush and invalidate
  153.  * the caches as needed.
  154.  * r3 = dest addr, r4 = source addr, r5 = copy limit, r6 = start offset
  155.  * on exit, r3, r4, r5 are unchanged, r6 is updated to be >= r5.
  156.  */
  157. copy_and_flush:
  158.     addi    r5,r5,-4
  159.     addi    r6,r6,-4
  160. @4:
  161.     li    r0,8
  162.     mtctr    r0
  163. @3:
  164.     addi    r6,r6,4            /* copy a cache line */
  165.     lwzx    r0,r6,r4
  166.     stwx    r0,r6,r3
  167.     bdnz    @3
  168.     dcbst    r6,r3            /* write it to memory */
  169.     __sync(3)
  170.     icbi    r6,r3            /* flush the icache line */
  171.     cmplw    r6,r5
  172.     blt        @4
  173.     isync
  174.     addi    r5,r5,4
  175.     addi    r6,r6,4
  176.     blr
  177.  
  178. /* Routine for invalidating all BATs */
  179. inval_BATs:
  180.     li        r3,0
  181.     mfspr    r28,PVR
  182.     rlwinm    r28,r28,16,16,31        /* r28 = 1 for 601, 4 for 604 */
  183.     cmpwi    r28,1
  184.     beq        is_601_2
  185.     mtdbatu r3,0
  186.     mtdbatu r3,1
  187.     mtdbatu r3,2
  188.     mtdbatu r3,3
  189. is_601_2:
  190.     mtibatu r3,0
  191.     mtibatl    r3,0
  192.     mtibatu r3,1
  193.     mtibatl r3,1
  194.     mtibatu r3,2
  195.     mtibatl r3,2
  196.     mtibatu r3,3
  197.     mtibatl r3,3
  198.     blr
  199.  
  200. /* Due to the PPC architecture (and according to the specifications), a
  201.  * series of tlbie which goes through a whole 256 MB segment always flushes 
  202.  * the whole TLB. This is obviously overkill and slow, but who cares ? 
  203.  * It takes about 1 ms on a 200 MHz 603e and works even if residual data 
  204.  * get the number of TLB entries wrong.
  205.  */
  206. flush_tlb:
  207.     lis        r28,0x1000
  208. flush_tlb_loop:
  209.     addic.  r28,r28,-0x1000
  210.     tlbie    r28
  211.     blt        flush_tlb_loop
  212.     
  213. /* tlbsync is not implemented on 601, so use sync which seems to be a superset
  214.  * of tlbsync in all cases and do not bother with CPU dependant code
  215.  */
  216.     __sync(4)
  217.     blr                    
  218.  
  219. }
  220.  
  221.